/*
	created time:2018/4/23
	author:Chason
	describe:算法
*/

class  Algorithm {
	public constructor() {
	}


	/*
		卡牌数组排序和比较每个元素的+1和下一个元素是否相同
	*/
	public static cardCompare(keyArr){	
		keyArr.sort(function(a,b){return Number(a)-Number(b)});	
		if(keyArr.length==1){return true}			
		for(let i=0;i<keyArr.length;i++){
				if(i==keyArr.length-1){break};
				let curI=Number(keyArr[i])+1;
				let nextI=Number(keyArr[i+1]);			
				if(curI!=nextI){
					return false;
				}
		}
		return true;
	}

	/*
		判断是否有王炸,有就返回false，没有就true
	*/
	public static isKingBomb(arr):boolean{
		let num=0;;
		for(let i=0;i<arr.length;i++){
			if((arr[i].name.indexOf("kkSking")!=-1)|| (arr[i].name.indexOf("kkBking")!=-1)){
				num++;
			}
		}
		if(num==2){
			return false;
		}else{
			return true;
		}
	}





	/*
		验证牌是否符合出牌规范
		arr:要出牌的数组
		不符合返回false
		符合返回--{
			type:类型string
			continuity:number   //主牌型的数量。这样的牌型是几顺:比如3不带,444555666777,这里就填写4.默认值1
			dai:   //后面牌型的数量。默认值0。部分这个属性才有值。其余都是0。 比如8888999966 炸弹带对子中，后面带了对6,那么这里就是1，代表1对。
				   //这几种有---炸弹带对,炸弹带单,飞机带对子,飞机带单.

		}
		函数在每个if非确定下来的牌型不要返回false,要在函数最后面再返回false。因为可能出现判断的情况符合语句下面的某种牌型。
	*/
	public static cardRule(arr):any{
		if(arr.length<=0){return false;}
		/*
			获取卡牌出现的次数,eg:
			{
				4:1,
				5:3
			}
		*/
		function getCardNumObj(arr){
			let obj={}
			for(let i=0;i<arr.length;i++){
					let name=arr[i].name.slice(2);
					if(!obj[name]){
						obj[name]=1;	
					}else{
						obj[name]++;
					}
			}
			return obj;
		}
		//卡牌出现次数
		let obj=getCardNumObj(arr);
		//卡牌号出现次数对象属性数组(卡牌名字)
		let keyArr=Object.keys(obj);

		//单
		if(arr.length==1){return {type:"single",continuity:1,dai:0}}


		//对子或者王炸或者连对
		if(arr.length%2==0){
			//对子或者王炸
			if(arr.length==2){
				let car1=arr[0].name;
				let car2=arr[1].name;
				//先判断是否是王炸--因为王炸名字后面也符合下面的car1==car2判断
				let allName=car1+car2;
				if((allName.indexOf("kkSking")!=-1)&&(allName.indexOf("kkBking")!=-1)){
					return {type:"kingBomb",continuity:1,dai:0}
				}
				if(car1.slice(2)==car2.slice(2)){
					return {type:"double",continuity:1,dai:0}
				}
			}else{
				//连对
				let isAllTwoDui=true;//是否全部是连对
				if(keyArr.length>=3){						
						isAllTwoDui=Algorithm.cardCompare(keyArr);
						if(keyArr.indexOf("T")!=-1){
							isAllTwoDui=false;
						}										
						if(isAllTwoDui){
							for(let i in obj){
								(obj[i]!=2)&&(isAllTwoDui=false) ;
							}
							if(isAllTwoDui){return{type:"lianDui",continuity:keyArr.length,dai:0}}				
						}
				}
				

			}
		}
   

        //判断纯炸弹不带--eg:44445555
		if(arr.length%4==0){
			let isBomb=true;
			for(let i in obj){
				obj[i]!=4 &&(isBomb=false);
			}
			if(isBomb){
				if(keyArr.length==1){
					return{
						type:"bomb",
						continuity:keyArr.length,
						dai:0
					}
				}
				isBomb=this.cardCompare(keyArr);
				if(isBomb){
					return{
						type:"bomb",
						continuity:keyArr.length,
						dai:0
					}
				}
			}
		}


		//判断炸弹带对---4444555566778899
		if(arr.length%2==0){
			let bombDaiDui=false;
			let otherArr=[];//除去炸弹的牌
			let bombArr=[];//炸弹牌的组数--几个炸弹
			//先判断卡牌是否有炸弹
			for(let i in obj){
				obj[i]==4 &&(bombDaiDui=true);
			}		
			//确定有炸弹
			if(bombDaiDui){				
				for(let i in obj){
					//如果剩余卡牌不是出现4次或者2次就over了
					obj[i]!=4 &&(obj[i]!=2) &&(bombDaiDui=false);	
					//把炸弹和不是炸弹牌方便后面判断。
					obj[i]!=4 &&(otherArr.push(i));
					obj[i]==4 &&(bombArr.push(i));
							
				}
				bombDaiDui && (bombDaiDui=this.cardCompare(bombArr));
				//判断是否带有王炸
				bombDaiDui && (bombDaiDui=this.isKingBomb(arr));			
				if(bombDaiDui){
					//1个炸弹最多有2个对子--这里长度代表的是炸弹的组数和其他牌的组数
					if(otherArr.length<=(bombArr.length)){
						return{
							type:"bombDaiDui",
							continuity:bombArr.length,
							dai:otherArr.length
						}
					}
				
				}
				
			}
		}


		//判断炸弹带单---444455556789
		if(true){
			let isBombDaiDan=false;
			let bombNum=[];//保存炸弹对象名字属性数组
			let otherNum=0;//除去炸弹后剩余卡牌
			//判断是否有炸弹,如果有保存起来
			for(let i in obj){
				if(obj[i]==4){
					isBombDaiDan=true;
					bombNum.push(i);	
				}
			}
			//判断炸弹是否连对
			isBombDaiDan && (isBombDaiDan=this.cardCompare(bombNum));
			//判断是否带有王炸
			isBombDaiDan && (isBombDaiDan=this.isKingBomb(arr));		
			//已经确定有炸弹，判断除去炸弹后剩余的卡牌数量
			if(isBombDaiDan){
				otherNum=arr.length-bombNum.length*4;
				if(otherNum<=bombNum.length*2){
					return{
						type:"bombDaiDan",
						continuity:bombNum.length,
						dai:otherNum

					}
				}		

			}	

		}	
		
		//判断顺子----3456789
		if(arr.length>=5){
			let isShunZi=true;
			//每种卡牌必须为一种
			for(let i in obj){
				if(obj[i]!=1){isShunZi=false;}
			}
			if(isShunZi){
				isShunZi=Algorithm.cardCompare(keyArr);
				if(isShunZi){
					return{
						type:"shunZi",
						continuity:arr.length,
						dai:0
				   }
				}
			}
		}

		//飞机带对子---33366 44477 55588 
		if(true){
			let isPlaneDouble=false;
			let sanArr=[];
			let otherObj={};//除去三卡牌相同后的卡牌组{卡牌名:数量}
			//判断是否有至少一组三张相同的卡牌,并取出来
			for(let i in obj){
				if(obj[i]==3){
					isPlaneDouble=true;
					sanArr.push(i);	
				}else{
					otherObj[i]=obj[i];
				}
			}
			
			//判断是否连对
			isPlaneDouble=Algorithm.cardCompare(sanArr);		
			if(isPlaneDouble){
				//判断除去三卡牌相同的卡牌后其余卡牌是否是对子
				let num=0;//几个对子
				for(let i in otherObj){
					if(otherObj[i]!=2){
						isPlaneDouble=false		
					}else{
						num++;
					}
				}
				if(isPlaneDouble){
					if(num<=sanArr.length){
						return{
							type:"PlaneDouble",
							continuity:sanArr.length,
							dai:num
						}
					}
				}

			}
		}

		//飞机带单--- eg:44455578
		if(true){
			let isPlaneSingle=false;
			let sanArr=[];
			let otherObj={};
			for(let i in obj){
				if(obj[i]==3){
					isPlaneSingle=true;
					sanArr.push(i);	
				}else{
					otherObj[i]=obj[i];
				}
			}
			//判断是否连对
			isPlaneSingle=Algorithm.cardCompare(sanArr);		
			if(isPlaneSingle){
				let num=0;
				for(let i in otherObj){
					num+=otherObj[i]
				}
				if(num<=sanArr.length){
					return{
						type:"planeSingle",
						continuity:sanArr.length,
						dai:num
					}
				}
			}
		}

		/*
		   3不带---eg:333
		    或者
		   飞机不带-- eg:444555666
		*/
		if(arr.length%3==0){			
			let isSan=true;//是否是--3不带牌型			
			//判断同一个牌是否出现3次,也只能三次
			for(let i in obj){
				if(obj[i]!=3){
                  isSan=false;
				}
			}
			//飞机---3不带
			if(keyArr.length==1){
				return { type:"san",continuity:keyArr.length,dai:0};
			}
			//多个3不带
			if(keyArr.indexOf("T")!=-1){
				isSan=false;
			}
			if(isSan){
				//判断是否是飞机不带				
				isSan=Algorithm.cardCompare(keyArr);	
				if(isSan){
					return { type:"plane",continuity:keyArr.length,dai:0};
				}

			}
				
		}

		//判断3带2--多种情况在飞机中
		if(arr.length==5){
			let isSanDaiTwo=false;
			if(keyArr.length==2){
				for(let i in obj){
					obj[i]==3 &&(isSanDaiTwo=true);
				}
				if(isSanDaiTwo){
					return {
						type:"sanDaiTwo",
						continuity:1,
						dai:0
					}
				}
			}
		}
		
		/*
			判断3带1--多种情况在飞机中
		*/	
		if(arr.length==4){			
			if(keyArr.length==2){
				let isSanDaiYi=false;
				for(let i in obj){
					obj[i]==3 &&(isSanDaiYi=true);
				}
				if(isSanDaiYi){return {"type":"sanDaiYi",continuity:1,dai:0}}
			}				
		}

		





		//如果上面都没有匹配到最后返回false
		return false;
	}



	/*
		模拟电脑出牌算法
		prevArr
		Arr
	*/
	public static compCardRule(prevArr,Arr){
		console.log("B出牌")
	}
}